package cn.com.easy.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import cn.com.easy.exception.BusinessException;
import cn.com.easy.pay.weixinpay.param.UnifiedOrderParam;

/**
 * java对象转Xml
 * 
 * @author nibili 2017年5月7日
 * 
 */
public class XmlUtils {

	public static void main(String[] args) throws Exception {
		UnifiedOrderParam unifiedOrderParam = new UnifiedOrderParam();
		unifiedOrderParam.setAppid("1");
		unifiedOrderParam.setAttach("2");
		unifiedOrderParam.setBody("3");
		//
		String xmlStr = XmlUtils.objectToXml(unifiedOrderParam);
		System.out.println(xmlStr);
		//
		UnifiedOrderParam unifiedOrderParam1 = XmlUtils.xmlStrToObject(UnifiedOrderParam.class, xmlStr);
		System.out.println(FastJSONUtils.toJsonString(unifiedOrderParam1));
		//
		System.out.println("-----");
		Map<String, Object> map = XmlUtils.xmlStrToObject(xmlStr);

		System.out.println(FastJSONUtils.toJsonString(map));
	}

	/**
	 * 对象转成Xml
	 * 
	 * @param object
	 * @return
	 * @throws JAXBException
	 * @throws BusinessException
	 * @author nibili 2017年5月7日
	 */
	public static String objectToXml(Object... objectes) throws JAXBException, BusinessException {
		if (objectes.length <= 0) {
			throw new BusinessException("对象不能为null");
		}
		Class<?>[] clazzes = new Class<?>[objectes.length];
		for (int i = 0, len = objectes.length; i < len; i++) {
			clazzes[i] = objectes[i].getClass();
		}
		JAXBContext context = JAXBContext.newInstance(clazzes); // 获取上下文对象
		Marshaller marshaller = context.createMarshaller(); // 根据上下文获取marshaller对象
		marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); // 设置编码字符集
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 格式化XML输出，有分行和缩进
		// marshaller.marshal(unifiedOrderParam, System.out); // 打印到控制台
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		marshaller.marshal(objectes[0], baos);
		String xmlObj = new String(baos.toByteArray()); // 生成XML字符串
		return xmlObj;
	}

	/**
	 * 将String类型的xml转换成对象
	 * 
	 * @param clazz
	 * @param xmlStr
	 * @return
	 * @throws JAXBException
	 * @author nibili 2017年5月7日
	 */
	@SuppressWarnings("unchecked")
	public static <T> T xmlStrToObject(Class<T> clazz, String xmlStr) throws JAXBException {
		T t = null;
		JAXBContext context = JAXBContext.newInstance(clazz);
		// 进行将Xml转成对象的核心接口
		Unmarshaller unmarshaller = context.createUnmarshaller();
		StringReader sr = new StringReader(xmlStr);
		t = (T) unmarshaller.unmarshal(sr);
		return t;
	}

	/**
	 * xml字符串转为map
	 * 
	 * @param xmlStr
	 * @return
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 * @author nibili 2017年5月11日
	 */
	public static Map<String, Object> xmlStrToObject(String xmlStr) throws ParserConfigurationException, SAXException, IOException {

		// 这里用Dom的方式解析回包的最主要目的是防止API新增回包字段
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		ByteArrayInputStream tInputStringStream = null;
		if (xmlStr != null && !xmlStr.trim().equals("")) {
			tInputStringStream = new ByteArrayInputStream(xmlStr.getBytes());
		}
		Document document = builder.parse(tInputStringStream);

		// 获取到document里面的全部结点
		NodeList allNodes = document.getFirstChild().getChildNodes();
		Node node;
		Map<String, Object> map = new HashMap<String, Object>();
		int i = 0;
		while (i < allNodes.getLength()) {
			node = allNodes.item(i);
			if (node instanceof Element) {
				map.put(node.getNodeName(), node.getTextContent());
			}
			i++;
		}
		return map;
	}
}
